package net.tcp;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.util.Scanner;

/**
 * 客户端tcp连接演示
 * @author fidel
 */
public class ClientDemo {
    public static void main(String[] args) throws IOException {
        Socket socket;
        BufferedReader bufferedReader;
        BufferedWriter bufferedWriter;
        Scanner input = new Scanner(System.in);
        String message;
        {
            // 创建一个流套接字并将其连接到指定主机上的指定端口号
            socket = new Socket("localhost", 18720);
            /*
             * 以套接字的输入流构造一个数据输入流
             * 数据输入流以一种与机器无关的方式从底层输入流中读取原始的Java数据类型
             * 注意：在多线程访问数据输入流的环境下，线程可能不安全
             */
            bufferedReader = getSocketBufferedReader(socket);
            System.out.println(bufferedReader.readLine());
            System.out.println(bufferedReader.readLine());
            /*
             * 以套接字的输出流构造一个数据输出流
             * 数据输出流允许应用程序以可移植的方式将原始的Java数据类型写入输出流
             * 应用程序可以使用数据输入流将数据读回
             */
            bufferedWriter = getSocketBufferedWriter(socket);
            message = input.nextLine();
            bufferedWriter.write(message);
            flushLine(bufferedWriter);
            System.out.println(bufferedReader.readLine());
            socket.close();
        }
        {
            // 创建一个未连接的套接字
            socket = new Socket();
            // 以指定主机名和端口构造一个套接字地址
            SocketAddress clientSocketAddress = new InetSocketAddress("localhost", 18721);
            SocketAddress serverSocketAddress = new InetSocketAddress("localhost", 18720);
            // 将套接字绑定到一个本地地址
            socket.bind(clientSocketAddress);
            // 将此套接字连接到服务端
            socket.connect(serverSocketAddress);
            bufferedReader = getSocketBufferedReader(socket);
            System.out.println(bufferedReader.readLine());
            System.out.println(bufferedReader.readLine());
            // 向服务端发送数据
            bufferedWriter = getSocketBufferedWriter(socket);
            message = input.nextLine();
            bufferedWriter.write(message);
            flushLine(bufferedWriter);
            System.out.println(bufferedReader.readLine());
            socket.close();
        }
        input.close();
    }
    
    public static BufferedReader getSocketBufferedReader(Socket socket) throws IOException {
        InputStream in = socket.getInputStream();
        InputStreamReader reader = new InputStreamReader(in);
        BufferedReader bufferedReader = new BufferedReader(reader);
        return bufferedReader;
    }
    
    public static BufferedWriter getSocketBufferedWriter(Socket socket) throws IOException {
        OutputStream out = socket.getOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(out);
        BufferedWriter bufferedWriter = new BufferedWriter(writer);
        return bufferedWriter;
    }
    
    public static void flushLine(BufferedWriter writer) throws IOException {
        writer.newLine();
        writer.flush();
    }
    
    public static PrintStream getPrintStream(Socket socket) throws IOException {
        OutputStream out = socket.getOutputStream();
        PrintStream print = new PrintStream(out);
        return print;
    }
}
